﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Xml;
using Common.Logging;
using In.Api.Dto.HisWs;
//using InDbContext;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net;
using In.Api.Dto.Notify;
using In.Api.Dto.Notify.Notification;
using System.Xml.Serialization;
using System.IO;
using System.Configuration;
using Rmq.Center;

namespace In.Api.Controllers
{ 
    public class NotifyController : ApiController
    {
    private static readonly ILog Logger = LogManager.GetLogger(typeof(NotifyController));

        /// <summary>
        /// 接收通知的统一入口 http://127.0.0.1:8083/Notify/Notification
        /// 1.中文字符统一采用utf-8编码。
        /// 2.HTTP提交必须为POST方式
        /// 3.POST的body数据格式如下
        /// <Notification><NotificationType>Halt</NotificationType><NotificationInfo>halt information</NotificationInfo></Notification>
        /// <Card><CardType>0</CardType><CardNo>2000000001</CardNo></Card>
        /// 4.所有输入参数都大小写敏感.
        /// 5.返回结果为纯文本方式,返回信息如下
        /// <?xml version=\"1.0\"?><Result><ResultCode>0</ResultCode><ResultDesc /></Result>
        /// </summary>
        /// <returns></returns>
        /// 

        private const string Success = "0";
        private const string Error = "1";
        private const string SuccessMsg = "调用成功";

        private const string NoticeHalt = "halt";
        private const string NoticeReport = "report";
        private const string NoticeRefund = "refund";
        private const string NoticeInPatient = "inpatient";
        private const string NoticeCommon = "common";

        private static readonly HttpClient HttpClient = new HttpClient();
        [HttpPost]
        [ActionName("Notification")]
        public string Notification(string requsetXml)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(requsetXml);
           XmlNode node= xmlDoc.SelectSingleNode("/req/NotificationType");
            if (node == null)
            {
                return GetResponseXml(Error, "节点NotificationType为空");
            }
            string notificationType = node.InnerText;
             node = xmlDoc.SelectSingleNode("/req/NotificationInfo");
            if (node == null)
            {
                return GetResponseXml(Error, "节点NotificationInfo为空");
            }
            string notificationInfo = node.InnerXml;
            string strCode = Success, strMsg = SuccessMsg;

            var result = new NotificationResponse() { ResultCode = strCode, ResultDesc = strMsg };

            try
            {
                switch (notificationType.ToLower())
                {
                    //halt info 
                    case NoticeHalt:
                        result = Halt(notificationInfo);
                        break;
                    //缴费,检验，检查
                    case NoticeCommon:
                        result = Common(notificationInfo);
                        break;
                    //退费通知
                    case NoticeRefund:
                        result = Refund(notificationInfo);
                        break;
                    //住院通知
                    case NoticeInPatient:
                        result = InPatient(notificationInfo);
                        break;
                    
                }

            }
            catch (Exception ex)
            {
                result.ResultCode = Error;
                result.ResultDesc = ex.Message;
            }
             
            return GetResponseXml(result.ResultCode, result.ResultDesc);
        }

        private string GetResponseXml(string resultCode,string resultDesc)
        {
            XmlDocument xmlDoc = new XmlDocument();
            XmlNode root = xmlDoc.CreateElement("res");

            XmlNode resultCodeNode = xmlDoc.CreateElement("resultCode");
            resultCodeNode.InnerText = resultCode;
            root.AppendChild(resultCodeNode);

            XmlNode resultDescNode = xmlDoc.CreateElement("resultDesc");
            resultDescNode.InnerText = resultDesc;
            root.AppendChild(resultDescNode);

            xmlDoc.AppendChild(root);

            return xmlDoc.InnerXml;
        }

        public NotificationResponse Halt(string info)
        {
            string strMsg;
            HaltInfo haltinfo = new HaltInfo();
            var strCode = ValidateHaltXml(info, out strMsg, out haltinfo);
            if (!strCode.Equals(Success))
            {
                return new NotificationResponse() { ResultCode = Error, ResultDesc = strMsg };
            }
            return ProcessHaltNotice(haltinfo);

        }

        public NotificationResponse Common(string info)
        {
            string strMsg;
            CommonNotice notice = new CommonNotice();
            string strCode = ValidateCommonXml(info, out strMsg,out notice);

            if (!strCode.Equals(Success))
            {
                return new NotificationResponse() { ResultCode = Error, ResultDesc = strMsg };
            }
            return ProcessCommonNotice(notice);
        }

        public NotificationResponse InPatient(string info)
        {
            string strMsg;
            InPatientNotice notice = new InPatientNotice();
            string strCode = ValidateInPatientXml(info, out strMsg, out notice);

            if (!strCode.Equals(Success))
            {
                return new NotificationResponse() { ResultCode = Error, ResultDesc = strMsg };
            }
            return ProcessInPatientNotice(notice);
        }

        public NotificationResponse Refund(string info)
        {
            string strMsg;
            RefundInfo notice = new RefundInfo();
            string strCode = ValidateRefundXml(info, out strMsg, out notice);

            if (!strCode.Equals(Success))
            {
                return new NotificationResponse() { ResultCode = Error, ResultDesc = strMsg };
            }
            return ProcessRefundNotice(notice);
        }

        public string ValidateHaltXml(string strXml, out string strMsg,out HaltInfo info)
        {
            strMsg = "";
            string strCode = Success;
            var xDoc = new XmlDocument();
            bool hasError = false;
            info = new HaltInfo();
            try
            {
                xDoc.LoadXml(strXml);
                
                XmlNode node = xDoc.SelectSingleNode("HaltInfo/HaltDate");
                info.HaltDate = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/DeptId");
                info.DeptId = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/DeptName");
                info.DeptName = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/DoctorId");
                info.DoctorId = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/DoctorName");
                info.DoctorName = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/TimeSlice");
                info.TimeSlice = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/RegType");
                info.RegType = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/StartTime");
                info.StartTime = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/EndTime");
                info.EndTime = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo/OPTime");
                info.OPTime = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("HaltInfo");
                if (node == null)
                {
                    hasError = true;
                    strMsg = "错误:结点HaltInfo为空";
                }
                else if (string.IsNullOrEmpty(info.HaltDate))
                {
                    hasError = true;
                    strMsg = "错误:停诊日期HaltDate有误";
                }
                else if (string.IsNullOrEmpty(info.DeptId))
                {
                    hasError = true;
                    strMsg = "错误:科室编号DeptId为空";
                }
                else if (string.IsNullOrEmpty(info.DoctorId))
                {
                    hasError = true;
                    strMsg = "错误:医生编号DoctorId为空";
                }
                else if (string.IsNullOrEmpty(info.TimeSlice))
                {
                    hasError = true;
                    strMsg = "错误:时段TimeSlice为空";
                }
                else if (string.IsNullOrEmpty(info.RegType))
                {
                    hasError = true;
                    strMsg = "错误:号类RegType为空";
                }
                else if (string.IsNullOrEmpty(info.StartTime))
                {
                    hasError = true;
                    strMsg = "错误:停诊开始时间StartTime为空";
                }
                else if (string.IsNullOrEmpty(info.EndTime))
                {
                    hasError = true;
                    strMsg = "错误:停诊结束时间EndTime为空";
                }
                else if (string.IsNullOrEmpty(info.OPTime))
                {
                    hasError = true;
                    strMsg = "错误:停诊操作时间有误";
                }
            }
            catch (Exception ex)
            {
                hasError = true;
                strMsg = ex.Message;
            }

            strCode = (hasError == true ? Error : Success);

            if (strCode.Equals(Success))
                strMsg = SuccessMsg;

            return strCode;
        }

        public string ValidateCommonXml(string strXml, out string strMsg,out CommonNotice info)
        {
            strMsg = "";
            string strCode = Success;

            var xDoc = new XmlDocument();
            bool hasError = false;
            info = new CommonNotice();
            try
            {
                xDoc.LoadXml(strXml);
                

                XmlNode node = xDoc.SelectSingleNode("CommonInfo/NoticeType");
                info.NoticeType = (node == null) ? -1 : node.InnerText.ToInt32OrDefault();

                node = xDoc.SelectSingleNode("CommonInfo/PatientId");
                info.PatientId = (node == null) ? "" : node.InnerText;

                //node = xDoc.SelectSingleNode("CommonInfo/CardNo");
                //info.CardNo = (node == null) ? "" : node.InnerText;

                //node = xDoc.SelectSingleNode("CommonInfo/Name");
                //info.Name = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("CommonInfo/NoticeTime");
                info.NoticeTime = (node == null) ? DateTime.MinValue : node.InnerText.ToDateTimeOrDefault();

                //node = xDoc.SelectSingleNode("CommonInfo/AppNo");
                //info.AppNo = (node == null) ? "" : node.InnerText;

                //node = xDoc.SelectSingleNode("CommonInfo/ClinicNo");
                //info.ClinicNo = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("CommonInfo");
                if (node == null)
                {
                    hasError = true;
                    strMsg = "错误:结点CommonInfo为空";
                }
                else if (string.IsNullOrEmpty(info.PatientId))
                {
                    hasError = true;
                    strMsg = "错误:病人编号PatientId为空";
                }
                else if (info.NoticeType == -1)
                {
                    hasError = true;
                    strMsg = "错误:通知类型有误";
                }
                else if (DateTime.MinValue.CompareTo(info.NoticeTime) == 0)
                {
                    hasError = true;
                    strMsg = "错误:通知时间NoticeTime为空";
                }
                //ret_value = !hasError;
            }
            catch (Exception ex)
            {
                hasError = true;
                strMsg = ex.Message;
            }

            strCode = (hasError == true ? Error : Success);

            if (strCode.Equals(Success))
                strMsg = SuccessMsg;

            return strCode;
        }

        public string ValidateRefundXml(string strXml, out string strMsg,out RefundInfo info)
        {
            strMsg = "";
            string strCode = Success;

            var xDoc = new XmlDocument();
            bool hasError = false;
            info = new RefundInfo();
            try
            {
                xDoc.LoadXml(strXml);
                
                XmlNode node = xDoc.SelectSingleNode("RefundInfo/RefundType");
                info.RefundType = (node == null) ? -1 : node.InnerText.ToInt32OrDefault();

                node = xDoc.SelectSingleNode("RefundInfo/PatientId");
                info.PatientId = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("RefundInfo/CardNo");
                info.CardNo = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("RefundInfo/Name");
                info.Name = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("RefundInfo/RefundTime");
                info.RefundTime = (node == null) ? DateTime.MinValue : node.InnerText.ToDateTimeOrDefault();

                node = xDoc.SelectSingleNode("RefundInfo/SumFee");
                info.SumFee = (node == null) ? -1 : node.InnerText.ToDecimalOrDefault();

                node = xDoc.SelectSingleNode("RefundInfo/OrderId");
                info.OrderId = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("RefundInfo/ClinicNo");
                info.ClinicNo = (node == null) ? "" : node.InnerText;
                
                node = xDoc.SelectSingleNode("RefundInfo");
                if (node == null)
                {
                    hasError = true;
                    strMsg = "错误:结点RefundInfo为空";
                }
                else if (string.IsNullOrEmpty(info.PatientId))
                {
                    hasError = true;
                    strMsg = "错误:病人编号PatientId为空";
                }
                else if (info.RefundType == -1)
                {
                    hasError = true;
                    strMsg = "错误:退费类型RefundType有误";
                }
                else if (DateTime.MinValue.CompareTo(info.RefundTime) == 0)
                {
                    hasError = true;
                    strMsg = "错误:通知时间RefundTime为空";
                }
                //ret_value = !hasError;
            }
            catch (Exception ex)
            {
                hasError = true;
                strMsg = ex.Message;
            }

            strCode = (hasError == true ? Error : Success);

            if (strCode.Equals(Success))
                strMsg = SuccessMsg;

            return strCode;
        }

        public string ValidateInPatientXml(string strXml, out string strMsg, out InPatientNotice info)
        {
            strMsg = "";
            string strCode = Success;

            var xDoc = new XmlDocument();
            bool hasError = false;
            info = new InPatientNotice();
            try
            {
                xDoc.LoadXml(strXml);
                XmlNode node = xDoc.SelectSingleNode("InPatientInfo/InfoType");
                info.InfoType = (node == null) ? "" : node.InnerText;
                node = xDoc.SelectSingleNode("InPatientInfo/PatientId");
                info.PatientId = (node == null) ? "" : node.InnerText;
                node = xDoc.SelectSingleNode("InPatientInfo/CardNo");
                info.CardNo = (node == null) ? "" : node.InnerText;
                node = xDoc.SelectSingleNode("InPatientInfo/CardType");
                info.CardType = (node == null) ? "" : node.InnerText;
                node = xDoc.SelectSingleNode("InPatientInfo/VisitId");
                info.VisitId = (node == null) ? "" : node.InnerText;
                node = xDoc.SelectSingleNode("InPatientInfo/InDate");
                info.InDate = (node == null) ? "" : node.InnerText;
                node = xDoc.SelectSingleNode("InPatientInfo/Name");
                info.Name = (node == null) ? "" : node.InnerText;

                node = xDoc.SelectSingleNode("InPatientInfo");
                if (node == null)
                {
                    hasError = true;
                    strMsg = "错误:结点InPatientInfo为空";
                }
                else if (string.IsNullOrEmpty(info.InfoType))
                {
                    hasError = true;
                    strMsg = "错误:住院通知类型InfoType为空";
                }
                else if (string.IsNullOrEmpty(info.PatientId))
                {
                    hasError = true;
                    strMsg = "错误:病人编号PatientId为空";
                }

                else if (string.IsNullOrEmpty(info.CardNo))
                {
                    hasError = true;
                    strMsg = "错误:卡号CardNo为空";
                }
                else if (string.IsNullOrEmpty(info.CardType))
                {
                    hasError = true;
                    strMsg = "错误:卡类型CardType为空";
                }
                else if (string.IsNullOrEmpty(info.VisitId))
                {
                    hasError = true;
                    strMsg = "错误:入院次数VisitId为空";
                }
                else if (string.IsNullOrEmpty(info.InDate))
                {
                    hasError = true;
                    strMsg = "错误:入院时间InDate为空";
                }
                else if (string.IsNullOrEmpty(info.Name))
                {
                    hasError = true;
                    strMsg = "错误:病人姓名Name为空";
                }
               
            }
            catch (Exception ex)
            {
                hasError = true;
                strMsg = ex.Message;
            }

            strCode = (hasError == true ? Error : Success);

            if (strCode.Equals(Success))
                strMsg = SuccessMsg;

            return strCode;
        }

        private NotificationResponse ProcessHaltNotice(HaltInfo haltInfo)
        {
            string strCode = Success, strMsg = SuccessMsg;

            var result = new NotificationResponse() { ResultCode = strCode, ResultDesc = strMsg };
            var notification = new NotificationRequest()
            {
                NotificationType = "HaltNotice",
                NotificationInfo = JsonConvert.SerializeObject(haltInfo)
            };
            Console.WriteLine("停诊通知:{0}", notification.NotificationInfo);

            try
            {
                //var wxApiAddress = ConfigurationManager.AppSettings["WxNotificationApiBaseAddress"];
                var alipayApiAddress = ConfigurationManager.AppSettings["AlipayNotificationApiBaseAddress"];

                var hospMessageProducer = new HospMessageProducer();
                hospMessageProducer.Publish(new HospMessageMsg()
                {
                    NotificationType = notification.NotificationType,
                    NotificationInfo = notification.NotificationInfo
                });

                HttpClient.PostAsJsonAsync(alipayApiAddress, notification);
            }
            catch (Exception e)
            {
                Logger.ErrorFormat("发送停诊通知出错：{0}", e.Message);
                result.ResultCode = Error;
                result.ResultDesc = e.Message;
            }
            return result;
        }
        private NotificationResponse ProcessCommonNotice(CommonNotice commonNotice)
        {
            string strCode = Success, strMsg = SuccessMsg;
            var result = new NotificationResponse() { ResultCode = strCode, ResultDesc = strMsg };

            var notification = new NotificationRequest()
            {
                NotificationType = "CommonNotice",
                NotificationInfo = JsonConvert.SerializeObject(commonNotice)
            };
            Console.WriteLine("一般通知:{0}", notification.NotificationInfo);

            try
            {
                //var wxApiAddress = ConfigurationManager.AppSettings["WxNotificationApiBaseAddress"];
                var alipayApiAddress = ConfigurationManager.AppSettings["AlipayNotificationApiBaseAddress"];

                var hospMessageProducer = new HospMessageProducer();
                hospMessageProducer.Publish(new HospMessageMsg()
                {
                    NotificationType = notification.NotificationType,
                    NotificationInfo = notification.NotificationInfo
                });

                HttpClient.PostAsJsonAsync(alipayApiAddress, notification);
            }
            catch (Exception e)
            {
                Logger.ErrorFormat("发送一般通知出错：{0}", e.Message);
                result.ResultCode = Error;
                result.ResultDesc = e.Message;
            }
            return result;
        }
        private NotificationResponse ProcessRefundNotice(RefundInfo refundInfo)
        {
            string strCode = Success, strMsg = SuccessMsg;
            var result = new NotificationResponse() { ResultCode = strCode, ResultDesc = strMsg };

            var notification = new NotificationRequest()
            {
                NotificationType = "RefundNotice",
                NotificationInfo = JsonConvert.SerializeObject(refundInfo)
            };
            Console.WriteLine("退款通知:{0}", notification.NotificationInfo);

            try
            {
                //var wxApiAddress = ConfigurationManager.AppSettings["WxNotificationApiBaseAddress"];
                var alipayApiAddress = ConfigurationManager.AppSettings["AlipayNotificationApiBaseAddress"];

                var hospMessageProducer = new HospMessageProducer();
                hospMessageProducer.Publish(new HospMessageMsg()
                {
                    NotificationType = notification.NotificationType,
                    NotificationInfo = notification.NotificationInfo
                });

                HttpClient.PostAsJsonAsync(alipayApiAddress, notification);
            }
            catch (Exception e)
            {
                Logger.ErrorFormat("发送退款通知出错：{0}", e.Message);
                result.ResultCode = Error;
                result.ResultDesc = e.Message;
            }
            return result;
        }
        private NotificationResponse ProcessInPatientNotice(InPatientNotice notice)
        {
            string strCode = Success, strMsg = SuccessMsg;
            var result = new NotificationResponse() { ResultCode = strCode, ResultDesc = strMsg };
            var notification = new NotificationRequest()
            {
                NotificationType = "InpatientNotice",
                NotificationInfo = JsonConvert.SerializeObject(notice)
            };
            Console.WriteLine("入院通知:{0}", notification.NotificationInfo);

            try
            {
                //var wxApiAddress = ConfigurationManager.AppSettings["WxNotificationApiBaseAddress"];
                var alipayApiAddress = ConfigurationManager.AppSettings["AlipayNotificationApiBaseAddress"];

                var hospMessageProducer = new HospMessageProducer();
                hospMessageProducer.Publish(new HospMessageMsg()
                {
                    NotificationType = notification.NotificationType,
                    NotificationInfo = notification.NotificationInfo
                });

                HttpClient.PostAsJsonAsync(alipayApiAddress, notification);
            }
            catch (Exception e)
            {
                Logger.ErrorFormat("发送入院通知出错：{0}", e.Message);
                result.ResultCode = Error;
                result.ResultDesc = e.Message;
            }
            return result;
        }
    }
}